(*********************** SIPS Module ************************

Title: SIPS Customized Common Routines, SVS Version
File: SIPSXM-SVS

Author: R.D.Villwock aka 'Big Bob'

First Written: September 18, 2006

Current Version: 1.51

Last Modified: June 5, 2007

*************************************************************)
{ ---------------- Data Constructor Functions ---------------- }
function on_init_AmtCC

  family Amt { Vib-Amt CC parameter family with std BtnMenu }

    declare ui_button Btn       { CC Menu launch button }

    declare CC          { CC#, 0 = unassigned, 128 = PW }    

    declare x     { Current panel location of Leg.Btn }

    declare y

    declare state  { Current state of button (on/off) }

    declare @cap   { Prefix of button caption }

  end family { BTime }

  Amt.cap := 'VibAmt CC'  { Menu-Button caption prefix }

  declare AmtCC    { Legacy Name for Amt.CC prior to V150 }

  if Global[G_PFC] < V150  { Updating from version prior to V150 }

    _read_persistent_var(AmtCC) { Recall prior panel setting }

    Amt.CC := AmtCC             { Use prior AmtCC when updating }

  else  { Initialize Leg.CC for 'fresh' install default }

    Amt.CC := 0                 { Default to unassigned }

  end if   

  _read_persistent_var(Amt.CC)  { If updating from self (V150) }

  SetBtn(Amt)         { Disp;ay prior or default CC assignment }  
end function { on_init_AmtCC }

function on_init_Depth
  family Depth { Depth parameter family with add-on BtnMenu }

    declare ui_knob Knob (0,MaxDepth,100)  { Depth amount in db }

    declare ui_value_edit Range (MinRng,MaxRng,1) { MIDI CC add-on range }

    declare iKnob  { Image of last Depth Knob setting }

    declare Kmax := MaxDepth               { Max allowed Depth amount }
    declare ui_button Btn      { CC Menu launch button }    

    declare CC     { CC#, 0 = unassigned, 128 = PW }

    declare x      { Current panel location of Depth.Btn }

    declare y

    declare state  { Current state of button (on/off) }

    declare @cap   { Prefix of button caption }     

  end family { Depth }
  set_text(Depth.Knob,' Depth')           { Name the Depth Knob and }
  set_knob_unit(Depth.Knob,KNOB_UNIT_DB)  { Set displayed units to db }

  Depth.cap := 'Depth CC'             { Menu-Button caption prefix }

  set_text(Depth.Range,'CC Range')    { Name add-on Range Edit control }

       { Legacy Panel Control Names for Depth stuff }

  declare $Depth   { Legacy Name for Depth.Knob prior to V150 }

  declare IDepth   { Legacy Name for Depth.iKnob prior to V150 }

  declare DepRng   { Legacy Name for Depth.Range prior to V150 }

  declare Dep_CC   { Legacy Name for Depth.CC prior to V150 }

  if Global[G_PFC] < V150  { Updating from version prior to V150 }

    _read_persistent_var($Depth)   { Recall prior panel settings }

    _read_persistent_var(IDepth)

    _read_persistent_var(DepRng)

    _read_persistent_var(Dep_CC)
    if Dep_CC = -1
      Dep_CC := PitchWheel
    end if

    Depth.Knob := $Depth     { Initialize to prior version parms }

    Depth.iKnob := IDepth

    Depth.Range := DepRng

    Depth.CC := Dep_CC

  else  { Set 'fresh' install defaults for Panel Parms }

    Depth.Knob := MainParms[uDepth] { Default it to Inst_0   }

    Depth.iKnob := Depth.Knob       { Default Image to same as Knob }

    Depth.Range := DefRng           { Standard initial range }

    Depth.CC := 0                   { Default to CC unassigned }     

  end if   

  _read_persistent_var(Depth.CC)      { Restore prior CC assignment }

  SetBtn(Depth)    
end function { on_init_Depth }

function on_init_Set_UIX

{ These constants are used for two main purposes. As 'Offsets' and 

  'handles. The 'Offsets' are used to access Preset parameters and

  the 'handles' are used in Panel Maps to specify what controls to

  display in the corresponding positions. Most Preset parms are also

  panel controls but not all panel controls are included in the Presets.

  Also, a few Preset parms are not actually controls. Actual controls

  are prefixed by a lower-case 'u' or 't'. Preset parm offsets that do

  not refer to a control are prefixed by a lower-case 'p'. For Panel

  Maps, the SetXY routine need not refer to this latter type and

  therefore these index values can be re-used by controls that aren't

  included in the Preset parms. }
  declare const uDepth    := 0   { Offsets for Key Parms }

  declare const uWidth    := 1

  declare const uSpeed    := 2  

  declare const uDwell    := 3

  declare const uVWidth   := 4

  declare const uVDepth   := 5

  declare const uSpdDrift := 6

  declare const uSpdPer   := 7

  declare const uWavDrift := 8

  declare const uWavPer   := 9

  declare const uOnset    := 10

  declare const uRise     := 11

  declare const uDecay    := 12

  declare const uSustain  := 13
  declare const uEnvMenu  := 14
  declare const uVibAmt   := 15    

  declare const uDepRng   := 16  { Offsets for extended parms }

  declare const uDepCC    := 17

  declare const uSpdRng   := 18

  declare const uSpdCC    := 19

  declare const uAmtCC    := 20
  declare const pLowKey   := 21  { Parm only, not a UI Control }

  declare const pTopKey   := 22  { Parm only, not a UI Control }
  
  declare const UP_Empty := uOnset { User preset empty when zero }
  declare const uPreset   := 21  { Remaining panel controls (not in presets) }

  declare const uAlpha    := 22

  declare const uBackSp   := 23

  declare const uEntChr   := 24

  declare const uLoCase   := 25

  declare const uErase    := 26

  declare const tNameDsp  := 27  { Panel Labels (tags) }

  declare const tImpErr   := 28

  declare const tDepCap   := 29

  declare const tWdthCap  := 30

  declare const tWavCap   := 31

  declare const tSpdCap   := 32

  declare const tVarCap   := 33
  declare const tEnvCap   := 34
  declare const tIRCap    := 35

  declare const tIRBox    := 36
  declare const MaxControl := tIRBox { Highest Control Index }  

  declare const xxx       := -1     { Unused anchor position }

end function { on_init_Set_UIX }


function on_init_Speed

  family Speed { Speed parameter family with add-on BtnMenu }

    declare ui_knob Knob (MinSpeed,MaxSpeed,100) { Vibrato Speed in Hz }

    declare ui_value_edit Range (MinRng,MaxRng,1) { MIDI CC add-on range }

    declare iKnob  { Image of last Speed Knob setting }

    declare Kmax := MaxSpeed { Max allowed Speed value }
    declare ui_button Btn      { CC Menu launch button }    
    declare CC     { CC#, 0 = unassigned, 128 = PW }

    declare x      { Current panel location of Speed.Btn }

    declare y

    declare state  { Current state of button (on/off) }

    declare @cap   { Prefix of button caption }            

  end family { Speed }

  set_text(Speed.Knob,' Speed')          { Name the Speed Knob and }  

  set_knob_unit(Speed.Knob,KNOB_UNIT_HZ) { Set unit display to Hz  }

  Speed.cap := 'Speed CC'            { Menu-Button caption prefix }
  set_text(Speed.Range,'CC Range')   { Name add-on Range Edit control }

       { Legacy Panel Control Names for Speed stuff }

  declare $Speed   { Legacy Name for Speed.Knob prior to V150 }

  declare ISpeed   { Legacy Name for Speed.iKnob prior to V150 }

  declare SpdRng   { Legacy Name for Speed.Range prior to V150 }

  declare Spd_CC   { Legacy Name for Speed.CC prior to V150 }

  if Global[G_PFC] < V150  { Updating from version prior to V150 }

    _read_persistent_var($Speed)   { Recall prior panel settings }

    _read_persistent_var(ISpeed)

    _read_persistent_var(SpdRng)

    _read_persistent_var(Spd_CC)
    if Spd_CC = -1
      Spd_CC := PitchWheel
    end if

    Speed.Knob := $Speed     { Initialize to prior version parms }

    Speed.iKnob := ISpeed

    Speed.Range := SpdRng

    Speed.CC := Spd_CC
  else  { Set 'fresh' install defaults for Panel Parms }

    Speed.Knob := MainParms[uSpeed] { Default it to Inst_0   }

    Speed.iKnob := Speed.Knob       { Default Image to same as Knob }

    Speed.Range := DefRng           { Standard initial range }

    Speed.CC := 0                   { Default to CC unassigned }     

  end if   

  _read_persistent_var(Speed.CC)     { Restore prior CC assignment }

  SetBtn(Speed)    

end function { on_init_Speed }


function on_init_Std_PanelMap   { Control Layout for the Standard SVS Panel }

  declare global StdPanel_Map[36] := ( ...

    uPreset,  tWdthCap,   tSpdCap,    tVarCap,   tEnvCap,    tIRCap, ...

     uDepth,    uWidth,    uSpeed,    uVWidth,    uOnset,    tIRBox, ...

        xxx,       xxx,       xxx,    uVDepth,     uRise,       xxx, ...

    tDepCap,   tWavCap, uSpdDrift,    uSpdPer,    uDecay,   uVibAmt, ...

    uDepRng,    uDwell,   uSpdRng,  uWavDrift,  uSustain,       xxx, ...

     uDepCC,       xxx,    uSpdCC,    uWavPer,  uEnvMenu,    uAmtCC)   

end function { on_init_Std_PanelMap }

{ ---------------- SVS Version of Common Routines --------------- }


function Fmt105

{ Converts V105 User Presets in PresetParms

  array to V150 format in UserParms array }

  declare const User_1 := 120  { V105 offset to first User Preset, SVS }

  declare i      { Parm index }

  declare j      { Preset Index }

  declare p105   { Pointer to PresetParms array }

  declare p110   { Pointer to UserParms array }

  

  p105 := User_1 { User Preset #1 starts here in V105 }

  p110 := 0      { User Preset #1 starts here in V110 } 

  for j := 1 to UserPresets  { Do User Presets one by one }

    for i := 0 to 5  { Xfr parms 0..5 from V105 SVS }

      UserParms[p110 + i] := PresetParms[p105 + i]

    end for

    for i := 6 to 7  { Unpack parms 6..7 from V105 of SVS }

      UserParms[p110 + i] := PresetParms[p105 + i] mod 1000

      inc(p110)      { Store as parms 6..9 of V110 }

      UserParms[p110 + i] := PresetParms[p105 + i] / 1000

    end for

    for i := 8 to 11 { Xfr parms 8..11 to parms 10..13 } 

      UserParms[p110 + i] := PresetParms[p105 + i]

    end for
    p110 := p110 - 2 { Reset index to parm 0 }

          { Defaults for new Key Parms }

    UserParms[p110 + uEnvMenu] := Amt_and_Env

    UserParms[p110 + uVibAmt] := DefAmt  
    { Now use tokens for parms not available from V105 }

    for i := 16 to MaxParms - 1 

      UserParms[p110 + i] := NoParm 

    end for
    p105 := p105 + 12  { Advance to next preset base }

    p110 := p110 + MaxParms
  end for

end function { Fmt105 }

function Fmt110
{ Converts V110 User Presets in UserParms

  array to V150 format in UserParms array }
  declare i
  declare j
  declare p0
  
  for j := 0 to UserPresets - 1
    p0 := j*MaxParms
    UserParms[p0 + pTopKey] := UserParms[p0 + 21] { These were 1 lower }
    UserParms[p0 + pLowKey] := UserParms[p0 + 20]
    for i := uAmtCC downto uDepRng  { These were 2 lower }
      UserParms[p0 + i] := UserParms[p0 + i - 2]
    end for
    { Set the two new key parms to their defaults }
    UserParms[p0 + uVibAmt] := DefAmt
    UserParms[p0 + uEnvMenu] := Amt_and_Env
    if UserParms[p0 + uDepCC] = -1
      UserParms[p0 + uDepCC] := 128  { Remap Pitch Wheel code }
    end if
    if UserParms[p0 + uSpdCC] = -1

      UserParms[p0 + uSpdCC] := 128  { Remap Pitch Wheel code }

    end if    
  end for
end function { Fmt110 }



function Load_KeyParms   { Load KeyParms from PresetBfr }

  LoadParm(Depth.iKnob,uDepth) 

  Depth.Knob := Depth.iKnob

  LoadParm(Width,uWidth)

  LoadParm(Speed.iKnob,uSpeed) 

  Speed.Knob := Speed.iKnob

  LoadParm(PkDwell,uDwell)

  LoadParm(WidthVar,uVWidth)

  LoadParm(DepthVar,uVDepth)

  LoadParm(SpdDrift,uSpdDrift)

  LoadParm(SpdPer,uSpdPer)

  LoadParm(WavDrift,uWavDrift)

  LoadParm(WavPer,uWavPer)

  LoadParm(Onset,uOnset)

  LoadParm(Rise,uRise)

  LoadParm(Decay,uDecay)

  LoadParm(Sustain,uSustain)
  LoadParm(EnvMenu,uEnvMenu)
  LoadParm(VibAmt,uVibAmt)
end function { Load_KeyParms }



function Load_XParms   { Load Extra Parms from PresetBfr }

  LoadParm(Depth.Range,uDepRng)

  LoadParm(Depth.CC,uDepCC)

  LoadParm(Speed.Range,uSpdRng)

  LoadParm(Speed.CC,uSpdCC)

  LoadParm(Amt.CC,uAmtCC)

  LoadParm(Global[G_Low_Key],pLowKey)

  LoadParm(Global[G_Top_Key],pTopKey)

  ShowIR  { Update IR display }

end function { Load_XParms }



function Recall_Preset(menu_index)

{ Retrieves Preset Parameters from either MainParms or UserParms }

  declare parm0  { Offset to 1st parm of preset }

  declare px     { PresetBfr index }

  

  if CC_Pending # 0  

    CC_Pending := -2  { Cancel any pending CC assignment }

  end if
  if menu_index < User0

    parm0 := menu_index*KeyParms

    for px := 0 to KeyParms - 1  

      PresetBfr[px] := MainParms[parm0 + px]

    end for  { Get parms for Built-In Preset selected }

  else { menu index indicates a User Preset }

    parm0 := (menu_index - User0)*MaxParms

    for px := 0 to MaxParms - 1

      PresetBfr[px] := UserParms[parm0 + px]

    end for { Get parms for User Preset selected }

  end if

  Load_KeyParms   { Recall Key Parms from buffer }

  if menu_index >= User0  { User Preset being recalled }

    Load_XParms         { Recall extra User parms }

  end if
  SetBtn(Amt)    { Restore BtnMenus for CC assignment }

  SetBtn(Depth)

  SetBtn(Speed)  

end function { Recall_Preset }



function Save_Preset(upx)

{ Save current panel parameter set in UserParms array at upx }

  declare parm0

  

  parm0 := upx*MaxParms

  UserParms[parm0 + uDepth]    := Depth.Knob

  UserParms[parm0 + uWidth]    := Width

  UserParms[parm0 + uSpeed]    := Speed.Knob

  UserParms[parm0 + uDwell]    := PkDwell

  UserParms[parm0 + uVWidth]   := WidthVar

  UserParms[parm0 + uVDepth]   := DepthVar 

  UserParms[parm0 + uSpdDrift] := SpdDrift

  UserParms[parm0 + uSpdPer]   := SpdPer

  UserParms[parm0 + uWavDrift] := WavDrift

  UserParms[parm0 + uWavPer]   := WavPer

  UserParms[parm0 + uOnset]    := Onset

  UserParms[parm0 + uRise]     := Rise

  UserParms[parm0 + uDecay]    := Decay

  UserParms[parm0 + uSustain]  := Sustain
  UserParms[parm0 + uEnvMenu]  := EnvMenu  

  UserParms[parm0 + uVibAmt]   := VibAmt
  UserParms[parm0 + uDepRng]   := Depth.Range

  UserParms[parm0 + uDepCC]    := Depth.CC

  UserParms[parm0 + uSpdRng]   := Speed.Range

  UserParms[parm0 + uSpdCC]    := Speed.CC

  UserParms[parm0 + uAmtCC]    := Amt.CC

  UserParms[parm0 + pLowKey]   := Global[G_Low_Key]

  UserParms[parm0 + pTopKey]   := Global[G_Top_Key]

end function { Save_Preset }

function SetXY(h,x,y)

{ Moves the Control whose assigned 'handle' is h, to position x,y on the panel.

  If x = 0 or y = 0, the Control will be hidden. This case statement ties the

  previously defined index constants to the corresponding control. Negative

  case indices are ignored because they are used by panel/sub-panel maps to

  indicate that no control is anchored in that position. NOTE: SetXY also sets

  the 'internal' x,y values for Button-Menus }

  if h >= 0  { Ignore negative h values }

    select h

      case uPreset                    { Col 1, Std Panel }

        move_control(Preset,x,y)

      case uDepth

        move_control(Depth.Knob,x,y)

      case tDepCap

        move_control(DepthCap,x,y)

      case uDepRng

        move_control(Depth.Range,x,y)

      case uDepCC

        move_control(Depth.Btn,x,y)
        Depth.x := x
        Depth.y := y

      case tWdthCap                    { Col 2, Std Panel }

        move_control(WidthCap,x,y)        

      case uWidth

        move_control(Width,x,y)

      case tWavCap

        move_control(WaveCap,x,y)

      case uDwell

        move_control(PkDwell,x,y)

      case tSpdCap                   { Col 3, Std Panel }

        move_control(SpeedCap,x,y)

      case uSpeed

        move_control(Speed.Knob,x,y)      

      case uSpdDrift

        move_control(SpdDrift,x,y)        

      case uSpdRng

        move_control(Speed.Range,x,y)
      case uSpdCC
        move_control(Speed.Btn,x,y)
        Speed.x := x
        Speed.y := y

      case tVarCap                   { Col 4, Std Panel }

        move_control(VarCap,x,y)

      case uVWidth

        move_control(WidthVar,x,y)        

      case uVDepth

        move_control(DepthVar,x,y)

      case uSpdPer

        move_control(SpdPer,x,y)        

      case uWavDrift

        move_control(WavDrift,x,y)        

      case uWavPer

        move_control(WavPer,x,y)

      case tEnvCap                   { Col 5, Std Panel }

        move_control(EnvCap,x,y)        

      case uOnset

        move_control(Onset,x,y)

      case uRise

        move_control(Rise,x,y)        

      case uDecay

        move_control(Decay,x,y)
      case uSustain

        move_control(Sustain,x,y)        

      case uAmtCC

        move_control(Amt.Btn,x,y)
        Amt.x := x
        Amt.y := y
      case tIRCap                    { Col 6, Std Panel }

        move_control(IRCap,x,y)        

      case tIRBox

        move_control(IR_Box,x,y)

      case uEnvMenu

        move_control(EnvMenu,x,y)

      case uVibAmt

        move_control(VibAmt,x,y)

      case tNameDsp                  { Col 1, Rename SubPanel }

        move_control(NameDisplay,x,y)

      case uBackSp

        move_control(BackSpace,x,y)

      case uErase

        move_control(EraseName,x,y)                

      case uAlpha                    { Col 2, Rename SubPanel }

        move_control(Alpha,x,y)

      case uEntChr

        move_control(EnterChar,x,y)  { Col 3, Rename SubPanel }

      case uLoCase

        move_control(LowerCase,x,y)

      case tImpErr                   { ErrPanel }

        move_control(AutoImportError,x,y)

      { end cases }  

    end select

  end if

end function { SetXY }


function Update_Panel

{ Update control panel to reflect assigned CC changes }

  if CC_NUM = Amt.CC      { Envelope amplitude control }

    VibAmt := CC[Amt.CC]*100/127  { Update VibAmt Knob }

  end if

  if CC_NUM = Speed.CC     { Update Speed Knob }

    Update_Knob(Speed)

  end if

  if CC_NUM = Depth.CC     { Update Depth Knob }

    Update_Knob(Depth)

  end if

end function { Update_Panel }